<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  <title>spring中的两种aop实现方式jdk动态代理和cglib代理 | Zhaoxi Blooooooooog</title>
  <meta name="keywords" content=" spring , aop ">
  <meta name="description" content="spring中的两种aop实现方式jdk动态代理和cglib代理 | Zhaoxi Blooooooooog">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="前言最近在重构代码, 为框架添加Autofac作为ioc容器, 在处理业务层时, 遇到不同Service相互依赖的问题, 俗称循环依赖. 后来经过讨论解决了这个问题, 这里记录一下我们的探索过程. 场景介绍A服务依赖于B服务作为构造函数的参数, B服务依赖于A服务作为构造函数的参数, demo代码如下:     public class ServiceA : IServiceA     {">
<meta name="keywords" content="ioc,循环依赖">
<meta property="og:type" content="article">
<meta property="og:title" content="ioc循环依赖的发现与解决">
<meta property="og:url" content="https://zhaoxiwork.gitee.io/zhaoxiwork.gitee.io/2019/09/16/ioc循环依赖的发现与解决/index.html">
<meta property="og:site_name" content="Zhaoxi Blooooooooog">
<meta property="og:description" content="前言最近在重构代码, 为框架添加Autofac作为ioc容器, 在处理业务层时, 遇到不同Service相互依赖的问题, 俗称循环依赖. 后来经过讨论解决了这个问题, 这里记录一下我们的探索过程. 场景介绍A服务依赖于B服务作为构造函数的参数, B服务依赖于A服务作为构造函数的参数, demo代码如下:     public class ServiceA : IServiceA     {">
<meta property="og:locale" content="zn-CN">
<meta property="og:updated_time" content="2019-09-18T13:14:07.356Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="ioc循环依赖的发现与解决">
<meta name="twitter:description" content="前言最近在重构代码, 为框架添加Autofac作为ioc容器, 在处理业务层时, 遇到不同Service相互依赖的问题, 俗称循环依赖. 后来经过讨论解决了这个问题, 这里记录一下我们的探索过程. 场景介绍A服务依赖于B服务作为构造函数的参数, B服务依赖于A服务作为构造函数的参数, demo代码如下:     public class ServiceA : IServiceA     {">


<link rel="icon" href="/img/avatar.jpg">

<link href="/css/style.css?v=1.0.1" rel="stylesheet">

<link href="/css/hl_theme/github.css?v=1.0.1" rel="stylesheet">

<link href="//cdn.bootcss.com/animate.css/3.5.2/animate.min.css" rel="stylesheet">
<link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="/js/jquery.autocomplete.min.js?v=1.0.1"></script>

<script src="//cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js"></script>
<script>
    hljs.initHighlightingOnLoad();
</script>

<script src="//cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js"></script>



<script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

<script src="/js/iconfont.js?v=1.0.1"></script>

</head>
<div style="display: none">
  <input class="theme_disqus_on" value="false">
  <input class="theme_preload_comment" value="false">
  <input class="theme_blog_path" value>
</div>

<body>
<aside class="nav">
    <div class="nav-left">
        <a href="/" class="avatar_target">
    <img class="avatar" src="/img/avatar.jpg" />
</a>
<div class="author">
    <span>Zhaoxi</span>
</div>

<div class="icon">
    
        
        <a title="github" href="https://github.com/zhao4xi" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-github"></use>
                </svg>
            
        </a>
        
    
        
        <a title="email" href="mailto:zhao4xi@126.com" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-email"></use>
                </svg>
            
        </a>
        
    
        
        <a title="qq" href="http://wpa.qq.com/msgrd?v=3&uin=517810353&site=qq&menu=yes" target="_blank">
            
                <svg class="iconfont-svg" aria-hidden="true">
                    <use xlink:href="#icon-qq"></use>
                </svg>
            
        </a>
        
    
</div>




<ul>
    <li><div class="all active">全部文章<small>(21)</small></div></li>
    
        
            
            <li><div data-rel="数据库">数据库<small>(2)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="Redis">Redis<small>(5)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="Spring">Spring<small>(4)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="协议">协议<small>(2)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="Java">Java<small>(5)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="框架">框架<small>(1)</small></div>
                
            </li>
            
        
    
        
            
            <li><div data-rel="算法">算法<small>(1)</small></div>
                
            </li>
            
        
    
</ul>
<div class="left-bottom">
    <div class="menus">
    
    
    
    
    </div>
    <div><a  class="friends">友链</a></div>
</div>
<input type="hidden" id="yelog_site_posts_number" value="21">
<input type="hidden" id="yelog_site_word_count" value="24.4k">
<div style="display: none">
    <span id="busuanzi_value_site_uv"></span>
    <span id="busuanzi_value_site_pv"></span>
</div>

    </div>
    <div class="nav-right">
        <div class="friends-area">
    <div class="friends-title">
        友情链接
        <i class="back-title-list"></i>
    </div>
    <div class="friends-content">
        <ul>
            
            <li><a target="_blank" href="http://yelog.org/">叶落阁</a></li>
            
        </ul>
    </div>
</div>
        <div class="title-list">
    <form onkeydown="if(event.keyCode==13){return false;}">
        <input class="search" type="text" placeholder="以 in: 开头进行全文搜索" autocomplete="off"id="local-search-input" >
        <i class="cross"></i>
        <span>
            <label for="tagswitch">Tags:</label>
            <input id="tagswitch" type="checkbox" style="display: none" />
            <i id="tagsWitchIcon"></i>
        </span>
    </form>
    <div class="tags-list">
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">MySQL</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">锁</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">redis</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color5">lock</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">spring</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">transaction</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">bean scope</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">Spring</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color4">tcp</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">spring mvc</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">ThreadLocal</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color5">http</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">https</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color4">ioc</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color5">循环依赖</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color4">aop</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color4">volatile</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">Thread Safe</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color1">Collection</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">Thread</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color2">Thread Pool</a>
    </li>
    
    <li class="article-tag-list-item">
        <a href="javascript:" class="color4">红黑树</a>
    </li>
    
    <div class="clearfix"></div>
</div>

    
    <div id="local-search-result">

    </div>
    
    <nav id="title-list-nav">
        
        <a  class="数据库 "
           href="/zhaoxiwork.gitee.io/2018/12/14/MySQL字段到底推不推荐使用null值/"
           data-tag="MySQL"
           data-author="" >
            <span class="post-title" title="MySQL字段到底推不推荐使用null值">MySQL字段到底推不推荐使用null值</span>
            <span class="post-date" title="2018-12-14 14:59:38">2018/12/14</span>
        </a>
        
        <a  class="数据库 "
           href="/zhaoxiwork.gitee.io/2019/01/03/Mysql实现乐观锁和悲观锁/"
           data-tag="MySQL,锁"
           data-author="" >
            <span class="post-title" title="MySQL实现乐观锁和悲观锁">MySQL实现乐观锁和悲观锁</span>
            <span class="post-date" title="2019-01-03 14:58:25">2019/01/03</span>
        </a>
        
        <a  class="Redis "
           href="/zhaoxiwork.gitee.io/2018/12/31/Redis为什么这么快之数据结构/"
           data-tag="redis"
           data-author="" >
            <span class="post-title" title="Redis为什么这么快之数据结构">Redis为什么这么快之数据结构</span>
            <span class="post-date" title="2018-12-31 15:15:35">2018/12/31</span>
        </a>
        
        <a  class="Redis "
           href="/zhaoxiwork.gitee.io/2019/01/03/Redis实现分布式锁/"
           data-tag="redis,lock"
           data-author="" >
            <span class="post-title" title="Redis实现分布式锁">Redis实现分布式锁</span>
            <span class="post-date" title="2019-01-03 15:17:22">2019/01/03</span>
        </a>
        
        <a  class="Redis "
           href="/zhaoxiwork.gitee.io/2019/01/01/Redis为什么这么快之服务器事件驱动/"
           data-tag="redis"
           data-author="" >
            <span class="post-title" title="Redis为什么这么快之服务器事件驱动">Redis为什么这么快之服务器事件驱动</span>
            <span class="post-date" title="2019-01-01 15:16:15">2019/01/01</span>
        </a>
        
        <a  class="Redis "
           href="/zhaoxiwork.gitee.io/2018/12/30/Redis的数据持久化方式/"
           data-tag="redis"
           data-author="" >
            <span class="post-title" title="Redis的数据持久化方式">Redis的数据持久化方式</span>
            <span class="post-date" title="2018-12-30 15:14:47">2018/12/30</span>
        </a>
        
        <a  class="Redis "
           href="/zhaoxiwork.gitee.io/2018/12/29/Redis的数据类型和基本使用/"
           data-tag="redis"
           data-author="" >
            <span class="post-title" title="Redis的数据类型和基本使用">Redis的数据类型和基本使用</span>
            <span class="post-date" title="2018-12-29 15:13:48">2018/12/29</span>
        </a>
        
        <a  class="Spring "
           href="/zhaoxiwork.gitee.io/2019/01/05/Spring-事务/"
           data-tag="spring,transaction"
           data-author="" >
            <span class="post-title" title="Spring 事务">Spring 事务</span>
            <span class="post-date" title="2019-01-05 14:49:55">2019/01/05</span>
        </a>
        
        <a  class="Spring "
           href="/zhaoxiwork.gitee.io/2018/12/26/Spring-Bean的作用域和生命周期/"
           data-tag="bean scope,Spring"
           data-author="" >
            <span class="post-title" title="Spring Bean的作用域和生命周期">Spring Bean的作用域和生命周期</span>
            <span class="post-date" title="2018-12-26 15:09:21">2018/12/26</span>
        </a>
        
        <a  class="协议 "
           href="/zhaoxiwork.gitee.io/2019/01/05/TCP-IP的三次握手和四次挥手/"
           data-tag="tcp"
           data-author="" >
            <span class="post-title" title="TCP/IP的三次握手和四次挥手">TCP/IP的三次握手和四次挥手</span>
            <span class="post-date" title="2019-01-05 14:51:46">2019/01/05</span>
        </a>
        
        <a  class="Spring "
           href="/zhaoxiwork.gitee.io/2018/12/27/Spring-MVC的请求处理流程/"
           data-tag="spring mvc"
           data-author="" >
            <span class="post-title" title="Spring MVC的请求处理流程">Spring MVC的请求处理流程</span>
            <span class="post-date" title="2018-12-27 15:11:12">2018/12/27</span>
        </a>
        
        <a  class="Java "
           href="/zhaoxiwork.gitee.io/2018/12/23/ThreadLocal使用场景及内存泄漏/"
           data-tag="ThreadLocal"
           data-author="" >
            <span class="post-title" title="ThreadLocal使用场景及内存泄漏">ThreadLocal使用场景及内存泄漏</span>
            <span class="post-date" title="2018-12-23 15:03:24">2018/12/23</span>
        </a>
        
        <a  class="协议 "
           href="/zhaoxiwork.gitee.io/2019/01/28/https和http的区别与比较/"
           data-tag="http,https"
           data-author="" >
            <span class="post-title" title="https和http的区别与比较">https和http的区别与比较</span>
            <span class="post-date" title="2019-01-28 09:37:25">2019/01/28</span>
        </a>
        
        <a  class="框架 "
           href="/zhaoxiwork.gitee.io/2019/09/16/ioc循环依赖的发现与解决/"
           data-tag="ioc,循环依赖"
           data-author="" >
            <span class="post-title" title="ioc循环依赖的发现与解决">ioc循环依赖的发现与解决</span>
            <span class="post-date" title="2019-09-16 10:30:51">2019/09/16</span>
        </a>
        
        <a  class=""
           href="/zhaoxiwork.gitee.io/2019/09/15/hello-world/"
           data-tag=""
           data-author="" >
            <span class="post-title" title="Hello World">Hello World</span>
            <span class="post-date" title="2019-09-15 22:07:00">2019/09/15</span>
        </a>
        
        <a  class="Spring "
           href="/zhaoxiwork.gitee.io/2018/12/25/spring中的两种aop实现方式jdk动态代理和cglib代理/"
           data-tag="spring,aop"
           data-author="" >
            <span class="post-title" title="spring中的两种aop实现方式jdk动态代理和cglib代理">spring中的两种aop实现方式jdk动态代理和cglib代理</span>
            <span class="post-date" title="2018-12-25 15:07:32">2018/12/25</span>
        </a>
        
        <a  class="Java "
           href="/zhaoxiwork.gitee.io/2018/12/23/volatile的使用方法及一些注意事项/"
           data-tag="volatile"
           data-author="" >
            <span class="post-title" title="volatile的使用方法及一些注意事项">volatile的使用方法及一些注意事项</span>
            <span class="post-date" title="2018-12-23 15:04:16">2018/12/23</span>
        </a>
        
        <a  class="Java "
           href="/zhaoxiwork.gitee.io/2018/12/17/如何实现线程安全/"
           data-tag="Thread Safe"
           data-author="" >
            <span class="post-title" title="如何实现线程安全">如何实现线程安全</span>
            <span class="post-date" title="2018-12-17 15:01:54">2018/12/17</span>
        </a>
        
        <a  class="Java "
           href="/zhaoxiwork.gitee.io/2018/12/24/常用Map的比较与实现-jdk1-8/"
           data-tag="Collection"
           data-author="" >
            <span class="post-title" title="常用Map的比较与实现(jdk1.8+)">常用Map的比较与实现(jdk1.8+)</span>
            <span class="post-date" title="2018-12-24 15:05:34">2018/12/24</span>
        </a>
        
        <a  class="Java "
           href="/zhaoxiwork.gitee.io/2018/12/15/深入理解Java线程池/"
           data-tag="Thread,Thread Pool"
           data-author="" >
            <span class="post-title" title="深入理解Java线程池">深入理解Java线程池</span>
            <span class="post-date" title="2018-12-15 15:00:51">2018/12/15</span>
        </a>
        
        <a  class="算法 "
           href="/zhaoxiwork.gitee.io/2018/12/29/红黑树的实现原理及应用/"
           data-tag="红黑树"
           data-author="" >
            <span class="post-title" title="红黑树的实现原理及应用">红黑树的实现原理及应用</span>
            <span class="post-date" title="2018-12-29 15:12:44">2018/12/29</span>
        </a>
        
    </nav>
</div>
    </div>
    <div class="hide-list">
        <div class="semicircle">
            <div class="brackets first"><</div>
            <div class="brackets">&gt;</div>
        </div>
    </div>
</aside>
<div class="post">
    <div class="pjax">
        <article id="post-spring中的两种aop实现方式jdk动态代理和cglib代理" class="article article-type-post" itemscope itemprop="blogPost">
    
        <h1 class="article-title">spring中的两种aop实现方式jdk动态代理和cglib代理</h1>
    
    <div class="article-meta">
        
        
        
        <span class="book">
            
                <a href="javascript:" data-rel="Spring">Spring</a>
            
        </span>
        
        
        <span class="tag">
            
            <a href="javascript:" class="color2">spring</a>
            
            <a href="javascript:" class="color4">aop</a>
            
        </span>
        
    </div>
    <div class="article-meta">
        
        创建时间:<time class="date" title='更新时间: 2019-09-21 15:18:59'>2018-12-25 15:07</time>
        
    </div>
    <div class="article-meta">
        
        <span>字数:1.3k</span>
        
        
        <span id="busuanzi_container_page_pv">
            阅读:<span id="busuanzi_value_page_pv">
                <span class="count-comment">
                    <span class="spinner">
                      <div class="cube1"></div>
                      <div class="cube2"></div>
                    </span>
                </span>
            </span>
        </span>
        
        
    </div>
    
    <div class="toc-ref">
    
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#aop的概念"><span class="toc-text">aop的概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#主要应用"><span class="toc-text">主要应用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#jdk动态代理"><span class="toc-text">jdk动态代理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#如何使用"><span class="toc-text">如何使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#动态代理的代理类生成过程"><span class="toc-text">动态代理的代理类生成过程</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#jdk动态代理的注意事项"><span class="toc-text">jdk动态代理的注意事项</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#cglib代理"><span class="toc-text">cglib代理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#如何使用-1"><span class="toc-text">如何使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#cglib代理的注意实现"><span class="toc-text">cglib代理的注意实现</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Spring中的aop概念"><span class="toc-text">Spring中的aop概念</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#定义"><span class="toc-text">定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#切面的示例"><span class="toc-text">切面的示例</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#spring的aop总结"><span class="toc-text">spring的aop总结</span></a></li></ol>
    
<style>
    .left-col .switch-btn,
    .left-col .switch-area {
        display: none;
    }
    .toc-level-3 i,
    .toc-level-3 ol {
        display: none !important;
    }
</style>
</div>
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="aop的概念"><a href="#aop的概念" class="headerlink" title="aop的概念"></a>aop的概念</h2><p>aop (Aspect Oriented Programming), 直译: 面向侧面编程, 通过 预编译方式 或者 动态代理 实现程序功能的统一维护的一种技术<br>带来的好处是: 可以对通用的业务逻辑独立, 降低通用逻辑和业务逻辑的耦合, 提高通用逻辑的重用性, 提高开发效率.</p>
<h2 id="主要应用"><a href="#主要应用" class="headerlink" title="主要应用"></a>主要应用</h2><p>统一日志记录, 性能统计, 统一授权, 事务处理, 统一异常处理.</p>
<h2 id="jdk动态代理"><a href="#jdk动态代理" class="headerlink" title="jdk动态代理"></a>jdk动态代理</h2><h4 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h4><p>实现利用java.lang.reflect.InvocationHandler接口, 重写其invoke方法为方法批量添加统一业务. </p>
<pre><code class="java">interface UserService {
    void insert(String userName);
}

class UserServiceImpl implements UserService {
    public void insert(String userName) {
        System.out.println(&quot;insert &quot; + userName);
    }
}

class UserServiceProxy implements InvocationHandler {
    private Object target;
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(&quot;before insert&quot;);
        Object result = method.invoke(target, args);
        System.out.println(&quot;after insert&quot;);
        return result;
    }
    public Object getProxy(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}

public class CglibAopDemo { 
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.insert(&quot;zhaoxi&quot;);// 只输出 insert zhaoxi
        UserServiceProxy proxy = new UserServiceProxy();
        UserService userServiceProxy = (UserService) proxy.getProxy(userService);
        userServiceProxy.insert(&quot;zhaoxi&quot;);
        //输出: before insert
        //insert zhaoxi
        //after insert
    }
} </code></pre>
<h4 id="动态代理的代理类生成过程"><a href="#动态代理的代理类生成过程" class="headerlink" title="动态代理的代理类生成过程"></a>动态代理的代理类生成过程</h4><ol>
<li>根据传入的ClassLoader和接口生成接口代理类的字节码</li>
<li>将自定义InvocationHandler对象作为代理类构造函数的参数, 传入代理类获取代理类的构造器</li>
<li>根据构造器来生成代理类的对象实例</li>
</ol>
<h4 id="jdk动态代理的注意事项"><a href="#jdk动态代理的注意事项" class="headerlink" title="jdk动态代理的注意事项"></a>jdk动态代理的注意事项</h4><ol>
<li>由于代理类继承了Proxy类, java不支持多继承, 所有只能代理接口, 不能代理类. </li>
</ol>
<h2 id="cglib代理"><a href="#cglib代理" class="headerlink" title="cglib代理"></a>cglib代理</h2><h4 id="如何使用-1"><a href="#如何使用-1" class="headerlink" title="如何使用"></a>如何使用</h4><p>使用CGLIB库, 实现库中MethodInterceptor 接口为方法添加统一业务<br>使用时需单独引入CGLIB库</p>
<pre><code class="java">class UserServiceCglib implements MethodInterceptor {
    private Object target;
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(&quot;before insert cglib&quot;);
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println(&quot;after insert cglib&quot;);
        return result;
    }
    public Object getTarget(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

public static void main(String[] args) {
    UserService userService = new UserServiceImpl();
    UserService userServiceProxy = (UserService) new UserServiceCglib().getTarget(userService);
    userServiceProxy.insert(&quot;zhaoxi&quot;);
    //输出 before insert cglib
    //insert zhaoxi
    //after insert cglib
}</code></pre>
<h4 id="cglib代理的注意实现"><a href="#cglib代理的注意实现" class="headerlink" title="cglib代理的注意实现"></a>cglib代理的注意实现</h4><ol>
<li>需要单独引入CGLIB库</li>
<li>不需要类继承接口, 但是不能将类设置为final, 因为使用继承生成代理.</li>
</ol>
<h2 id="Spring中的aop概念"><a href="#Spring中的aop概念" class="headerlink" title="Spring中的aop概念"></a>Spring中的aop概念</h2><h4 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h4><ul>
<li>Joinpoint : 连接点(在哪里), 在什么地方执行 增强操作, spring只支持方法级的连接点.</li>
<li>Pointcut : 切点是一组连接点的集合(在哪里干的集合).<ol>
<li>切点表达式介绍  execution(* fun.zhaoxi.aop..<em>.</em>(..))</li>
<li>execution() 是表达式的主体</li>
<li>括号中第一个 * 是方法的返回值, * 代表所有</li>
<li>fun.zhaoxi.aop.. 前面是包名的前缀, .. 代表子包和孙包中的所有类</li>
<li><em>.</em> 代表类名和方法名, * 代表所有</li>
<li>(..) 代表方法中的参数, .. 代表所有</li>
</ol>
</li>
<li>Advice : 增强(干什么), 一般是我们的公共业务.</li>
<li>Aspect : 切面(在哪儿干和干什么的集合), SpringAop就是负责操作切面并执行.<br>  切面类型:  <ol>
<li>@Before 前置通知</li>
<li>@After 后置通知</li>
<li>@AfterReturning 目标方法执行结束后执行</li>
<li>@AfterThrowing 目标方法异常执行</li>
<li>@Around 环绕通知, 目标方法执行前后都执行<br>目标方法正确的执行顺序是<br>5 → 1 → target() → 5 → 2 → 3.</li>
</ol>
</li>
</ul>
<h4 id="切面的示例"><a href="#切面的示例" class="headerlink" title="切面的示例"></a>切面的示例</h4><p>下面示例需要引入 spring-core, spring-context, spring-beans, spring-aop, spring-aspects 包<br>默认使用SDK动态代理, 如果使用CGLIB代理, 需要单独引入CGLIB库.</p>
<pre><code class="java">
interface UserService {
    void insert(String userName);
}

@Component
class UserServiceImpl implements UserService {
    public void insert(String userName) {
        System.out.println(&quot;insert &quot; + userName);
    }
}

@Component
@Aspect // 切面
class UserServiceAspect { 
    @Pointcut(&quot;execution(* fun.zhaoxi.aop.*.*(..))&quot;) //切点 参数为切点表达式
    public void pointcut() {
    }
    @Before(&quot;pointcut()&quot;)
    public void insertBefore() { //增强
        System.out.println(&quot;spring aop insert before&quot;);
    }
    @After(&quot;pointcut()&quot;)
    public void insertAfter() { //增强
        System.out.println(&quot;spring aop insert after&quot;);
    }
    @Around(&quot;pointcut()&quot;)
    public void insertAround(ProceedingJoinPoint point) throws Throwable { //增强
        System.out.println(&quot;spring aop insert around before&quot;);
        point.proceed();
        System.out.println(&quot;spring aop insert around after&quot;);
    }
    @AfterReturning(&quot;pointcut()&quot;)
    public void insertAfterReturning() { //增强
        System.out.println(&quot;spring aop insert afterReturning&quot;);
    }
    @AfterThrowing(&quot;pointcut()&quot;)
    public void insertAfterThrow() { //增强
        System.out.println(&quot;spring aop insert afterThrow&quot;);
    }
}

//spring-aop.xml: 放入resources文件夹
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:aop=&quot;http://www.springframework.org/schema/aop&quot;
       xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd&quot;&gt;

    &lt;aop:aspectj-autoproxy/&gt; &lt;!-- 如果要使用cglib代理, 添加 proxy-target-class=&quot;true&quot;, 需引入 cglib 包 --&gt;
    &lt;context:component-scan base-package=&quot;fun.zhaoxi.aop&quot; /&gt;&lt;!-- 包名是 service的包名 --&gt;
&lt;/beans&gt;

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(&quot;spring-aop.xml&quot;);
    UserService userService = applicationContext.getBean(UserService.class);
    userService.insert(&quot;zhaoxi&quot;);
}

//输出:
// spring aop insert around before
// spring aop insert before
// insert zhaoxi
// spring aop insert around after
// spring aop insert after
// spring aop insert afterReturning</code></pre>
<h2 id="spring的aop总结"><a href="#spring的aop总结" class="headerlink" title="spring的aop总结"></a>spring的aop总结</h2><p>aop是spring的核心功能之一, 要玩转spring, 肯定要深入了解.<br>在spring中 缓存, 错误处理, 事务, 等等功能都有aop的身影, 但是真正能发挥强大功能的是 ioc + aop.</p>

      
       <hr><span style="font-style: italic;color: gray;"> 转载请注明来源，欢迎对文章中的引用来源进行考证，欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论，也可以邮件至 zhao4xi@126.com </span>
    </div>
</article>



<div class="article_copyright">
    <p><span class="copy-title">文章标题:</span>spring中的两种aop实现方式jdk动态代理和cglib代理</p>
    <p><span class="copy-title">文章字数:</span><span class="post-count">1.3k</span></p>
    <p><span class="copy-title">本文作者:</span><a href="javascript:void(0)" title="Zhaoxi">Zhaoxi</a></p>
    <p><span class="copy-title">发布时间:</span>2018-12-25, 15:07:32</p>
    <p><span class="copy-title">最后更新:</span>2019-09-21, 15:18:59</p>
    <span class="copy-title">原始链接:</span><a class="post-url" href="/zhaoxiwork.gitee.io/2018/12/25/spring中的两种aop实现方式jdk动态代理和cglib代理/" title="spring中的两种aop实现方式jdk动态代理和cglib代理">https://zhaoxiwork.gitee.io/zhaoxiwork.gitee.io/2018/12/25/spring中的两种aop实现方式jdk动态代理和cglib代理/</a>
    <p>
        <span class="copy-title">版权声明:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" title="CC BY-NC-SA 4.0 International" target = "_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。
    </p>
</div>





    




    </div>
    <div class="copyright">
        <p class="footer-entry">©2016-2019 Zhaoxi</p>
<p class="footer-entry">Built with <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/yelog/hexo-theme-3-hexo" target="_blank">3-hexo</a> theme</p>

    </div>
    <div class="full-toc">
        <button class="full"><span class="min "></span></button>
<button class="post-toc-menu"><span class="post-toc-menu-icons"></span></button>
<div class="post-toc"><span class="post-toc-title">目录</span>
    <div class="post-toc-content">

    </div>
</div>
<a class="" id="rocket" href="javascript:void(0)"></a>
    </div>
</div>
<div class="acParent"></div>

</body>
<script src="/js/jquery.pjax.js?v=1.0.1" ></script>

<script src="/js/script.js?v=1.0.1" ></script>
<script>
    var img_resize = 'default';
    /*作者、标签的自动补全*/
    $(function () {
        $('.search').AutoComplete({
            'data': ['#MySQL','#锁','#redis','#lock','#spring','#transaction','#bean scope','#Spring','#tcp','#spring mvc','#ThreadLocal','#http','#https','#ioc','#循环依赖','#aop','#volatile','#Thread Safe','#Collection','#Thread','#Thread Pool','#红黑树',],
            'itemHeight': 20,
            'width': 418
        }).AutoComplete('show');
    })
    function initArticle() {
        /*渲染对应的表格样式*/
        
            $(".post .pjax table").addClass("green_title");
        

        /*渲染打赏样式*/
        

        /*高亮代码块行号*/
        
        $('pre code').each(function(){
            var lines = $(this).text().split('\n').length - 1, widther='';
            if (lines>99) {
                widther = 'widther'
            }
            var $numbering = $('<ul/>').addClass('pre-numbering ' + widther).attr("unselectable","on");
            $(this).addClass('has-numbering ' + widther)
                    .parent()
                    .append($numbering);
            for(var i=1;i<=lines;i++){
                $numbering.append($('<li/>').text(i));
            }
        });
        

        /*访问数量*/
        
        $.getScript("//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js");
        

        /*代码高亮，行号对齐*/
        $('.pre-numbering').css('line-height',$('.has-numbering').css('line-height'));

        
    }

    /*打赏页面隐藏与展示*/
    

</script>

<!--加入行号的高亮代码块样式-->

<style>
    pre{
        position: relative;
        margin-bottom: 24px;
        border-radius: 10px;
        border: 1px solid #e2dede;
        background: #FFF;
        overflow: hidden;
    }
    code.has-numbering{
        margin-left: 30px;
    }
    code.has-numbering.widther{
        margin-left: 35px;
    }
    .pre-numbering{
        margin: 0px;
        position: absolute;
        top: 0;
        left: 0;
        width: 20px;
        padding: 0.5em 3px 0.7em 5px;
        border-right: 1px solid #C3CCD0;
        text-align: right;
        color: #AAA;
        background-color: ;
    }
    .pre-numbering.widther {
        width: 35px;
    }
</style>

<!--自定义样式设置-->
<style>
    
    
    .nav {
        width: 542px;
    }
    .nav.fullscreen {
        margin-left: -542px;
    }
    .nav-left {
        width: 120px;
    }
    
    
    @media screen and (max-width: 1468px) {
        .nav {
            width: 492px;
        }
        .nav.fullscreen {
            margin-left: -492px;
        }
        .nav-left {
            width: 100px;
        }
    }
    
    
    @media screen and (max-width: 1024px) {
        .nav {
            width: 492px;
            margin-left: -492px
        }
        .nav.fullscreen {
            margin-left: 0;
        }
        .nav .hide-list.fullscreen {
            left: 492px
        }
    }
    
    @media screen and (max-width: 426px) {
        .nav {
            width: 100%;
        }
        .nav-left {
            width: 100%;
        }
    }
    
    
    .nav-right .title-list nav a .post-title, .nav-right .title-list #local-search-result a .post-title {
        color: #383636;
    }
    
    
    .nav-right .title-list nav a .post-date, .nav-right .title-list #local-search-result a .post-date {
        color: #5e5e5f;
    }
    
    
    .nav-right nav a.hover, #local-search-result a.hover{
        background-color: #e2e0e0;
    }
    
    

    /*列表样式*/
    
    .post .pjax article .article-entry>ol, .post .pjax article .article-entry>ul, .post .pjax article>ol, .post .pjax article>ul{
        border: #e2dede solid 1px;
        border-radius: 10px;
        padding: 10px 32px 10px 56px;
    }
    .post .pjax article .article-entry li>ol, .post .pjax article .article-entry li>ul,.post .pjax article li>ol, .post .pjax article li>ul{
        padding-top: 5px;
        padding-bottom: 5px;
    }
    .post .pjax article .article-entry>ol>li, .post .pjax article .article-entry>ul>li,.post .pjax article>ol>li, .post .pjax article>ul>li{
        margin-bottom: auto;
        margin-left: auto;
    }
    .post .pjax article .article-entry li>ol>li, .post .pjax article .article-entry li>ul>li,.post .pjax article li>ol>li, .post .pjax article li>ul>li{
        margin-bottom: auto;
        margin-left: auto;
    }
    

    /* 背景图样式 */
    
    


    /*引用块样式*/
    

    /*文章列表背景图*/
    
    .nav-right:before {
        content: ' ';
        display: block;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        opacity: 0.3;
        background: url("https://i.loli.net/2019/07/22/5d3521411f3f169375.png");
        background-repeat: no-repeat;
        background-position: 50% 0;
        -ms-background-size: cover;
        -o-background-size: cover;
        -moz-background-size: cover;
        -webkit-background-size: cover;
        background-size: cover;
    }
    

    
</style>







</html>
